home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 684 / 684.xpi / chrome / fireftp.jar / content / js / local / localDirTree.js next >
Text File  |  2008-08-01  |  25KB  |  571 lines

  1. var localDirTree = {
  2.   data         : new Array(),
  3.   rowCount     : 0,
  4.   exceptions   : new Array(),
  5.   dirtyList    : new Array(),
  6.   ignoreSelect : false,
  7.  
  8.   getCellText         : function(row, column)       { return this.data[row].leafName; },
  9.   getLevel            : function(row)               { return this.data[row].level; },
  10.   getParentIndex      : function(row)               { return this.data[row].parentIndex; },
  11.   getImageSrc         : function(row, col)          { },
  12.   getColumnProperties : function(colid, col, props) { },
  13.   getRowProperties    : function(row, props)        { },
  14.   hasNextSibling      : function(row, nextrow)      { return this.data[row].hasNext; },
  15.   isContainer         : function(row)               { return true; },
  16.   isContainerEmpty    : function(row)               { return this.data[row].empty; },
  17.   isContainerOpen     : function(row)               { return this.data[row].open; },
  18.   isSeparator         : function(row)               { return false; },
  19.   isSorted            : function(row)               { return false; },
  20.   setTree             : function(treebox)           { this.treebox = treebox; },
  21.  
  22.   getCellProperties : function(row, col, props)   {
  23.     if (row >= 0 && row < this.data.length && this.data[row]) {
  24.       if (this.data[row].isHidden) {
  25.         props.AppendElement(gAtomService.getAtom("hidden"));
  26.       }
  27.     }
  28.   },
  29.  
  30.   toggleOpenState     : function(row, suppressChange) {
  31.     var doOpen = true;
  32.  
  33.     if (this.isContainerOpen(row)) {
  34.       doOpen = false;
  35.       var level     = this.data[row].level;
  36.       var lastChild = row;
  37.  
  38.       while (lastChild + 1 < this.rowCount && this.data[lastChild + 1].level > level) {            // find last index in same level as collapsed dir
  39.         ++lastChild;
  40.       }
  41.  
  42.       this.data[row].children = this.data.splice(row + 1, lastChild - row);                        // get rid of subdirectories from view
  43.       this.updateParentIndices();
  44.       this.rowCount = this.data.length;
  45.       this.treebox.rowCountChanged(row, -(lastChild - row));
  46.  
  47.       this.data[row].open = false;
  48.       this.treebox.invalidateRow(row);                                                             // update row
  49.  
  50.       var localPathSlash = gLocalPath.value    + (gLocalPath.value.charAt(gLocalPath.value.length - 1)       != gSlash ? gSlash : '');
  51.       var dataPathSlash  = this.data[row].path + (this.data[row].path.charAt(this.data[row].path.length - 1) != gSlash ? gSlash : '');
  52.  
  53.       if (localPathSlash.indexOf(dataPathSlash) == 0 && gLocalPath.value != this.data[row].path
  54.        && gLocalPath.value.match(gSlash == "/" ? /\x2f/g : /\x5c/g ).length > this.data[row].level && !suppressChange) {
  55.         gLocalPath.value = this.data[row].path;                                                    // we were in a subdirectory and we collapsed
  56.         this.selection.select(row);
  57.         this.treebox.ensureRowIsVisible(row);
  58.         localTree.updateView();
  59.       } else if (gLocalPath.value == this.data[row].path) {
  60.         this.selection.select(row);
  61.         this.treebox.ensureRowIsVisible(row);
  62.       }
  63.     } else {
  64.       for (var x = 0; x < this.dirtyList.length; ++x) {                                            // see if the row is dirty
  65.         if (this.dirtyList[x] == this.data[row].path) {
  66.           this.dirtyList.splice(x, 1);
  67.           this.data[row].children = null;
  68.           break;
  69.         }
  70.       }
  71.  
  72.       if (this.data[row].children) {                                                               // see if any of the rows children are dirty
  73.         for (var x = 0; x < this.dirtyList.length; ++x) {
  74.           var found = false;
  75.  
  76.           for (var y = this.data[row].children.length - 1; y >= 0; --y) {
  77.             if (this.data[row].children[y].path == this.dirtyList[x]) {
  78.               found = true;
  79.               this.data[row].children[y].children = null;
  80.               this.data[row].children[y].open     = false;
  81.               this.data[row].children[y].empty    = false;
  82.             } else if (this.data[row].children[y].path.indexOf(this.dirtyList[x]
  83.                                                             + (this.dirtyList[x].charAt(this.dirtyList[x].length - 1) != gSlash ? gSlash : '')) == 0) {
  84.               found = true;
  85.               this.data[row].children.splice(y, 1);
  86.             }
  87.           }
  88.  
  89.           if (found) {
  90.             this.dirtyList.splice(x, 1);
  91.           }
  92.         }
  93.       }
  94.  
  95.       if (this.data[row].children) {                                                               // stored from before
  96.         for (var x = this.data[row].children.length - 1; x >= 0; --x) {
  97.           this.data.splice(row + 1, 0, this.data[row].children[x]);
  98.         }
  99.  
  100.         this.updateParentIndices();
  101.         this.rowCount           = this.data.length;
  102.         this.treebox.rowCountChanged(row + 1, this.data[row].children.length);
  103.         this.data[row].children = null;
  104.         this.data[row].open     = true;
  105.         this.treebox.invalidateRow(row);
  106.       } else {                                                                                     // get data for this directory
  107.         var newDirectories = new Array();
  108.  
  109.         try {
  110.           var dir     = localFile.init(this.data[row].path);
  111.           var entries = dir.directoryEntries;
  112.  
  113.           while (entries.hasMoreElements()) {
  114.             var file          = entries.getNext().QueryInterface(Components.interfaces.nsILocalFile);// get subdirectories
  115.             var isParent      = false;
  116.             var isException   = false;
  117.             var filePathSlash = file.path + (file.path.charAt(file.path.length - 1) != gSlash ? gSlash : '');
  118.  
  119.             if (file.exists() && localFile.testSize(file) && file.isDirectory() && this.findDirectory) {                       // we're navigating to a directory that might be hidden
  120.               var findDirectorySlash = this.findDirectory.path
  121.                                     + (this.findDirectory.path.charAt(this.findDirectory.path.length - 1) != gSlash ? gSlash : '');
  122.  
  123.               if (gSlash == "/") {
  124.                 isParent    = findDirectorySlash.indexOf(filePathSlash) == 0;
  125.               } else {
  126.                 isParent    = findDirectorySlash.toLowerCase().indexOf(filePathSlash.toLowerCase()) == 0;
  127.               }
  128.  
  129.               if (isParent) {
  130.                 this.exceptions.push(this.findDirectory);
  131.               }
  132.             }
  133.  
  134.             for (var x = 0; x < this.exceptions.length; ++x) {
  135.               var exceptionsSlash = this.exceptions[x].path + (this.exceptions[x].path.charAt(this.exceptions[x].path.length - 1) != gSlash ? gSlash : '');
  136.  
  137.               if (gSlash == "/") {
  138.                 isException  = exceptionsSlash.indexOf(filePathSlash) == 0;
  139.               } else {
  140.                 isException  = exceptionsSlash.toLowerCase().indexOf(filePathSlash.toLowerCase()) == 0;
  141.               }
  142.  
  143.               if (isException) {
  144.                 break;
  145.               }
  146.             }
  147.  
  148.             if (file.exists() && localFile.testSize(file) && file.isDirectory() && (!file.isHidden() || gFtp.hiddenMode || isParent || isException)) {
  149.               newDirectories.push(file);
  150.             }
  151.           }
  152.         } catch (ex) {
  153.           debug(ex);
  154.           error(gStrbundle.getString("noPermission"));
  155.         }
  156.  
  157.         if (newDirectories.length == 0)  {                                                         // no subdirectories
  158.           this.data[row].empty = true;
  159.           this.data[row].open  = false;
  160.         } else {                                                                                   // has subdirectories
  161.           for (var x = 0; x < newDirectories.length; ++x) {
  162.             newDirectories[x] = { open        : false,
  163.                                   empty       : false,
  164.                                   hasNext     : true,
  165.                                   parentIndex : -1,
  166.                                   children    : null,
  167.                                   path        : newDirectories[x].path,
  168.                                   leafName    : newDirectories[x].leafName,
  169.                                   parent      : newDirectories[x].parent ? newDirectories[x].parent.path : "",
  170.                                   isHidden    : newDirectories[x].isHidden(),
  171.                                   level       : newDirectories[x].path.match(  gSlash == "/" ? /\x2f/g : /\x5c/g).length,
  172.                                   sortPath    : newDirectories[x].path.replace(gSlash == "/" ? /\x2f/g : /\x5c/g, "\x01").toLowerCase() };
  173.           }
  174.  
  175.           newDirectories.sort(directorySort);
  176.           newDirectories[newDirectories.length - 1].hasNext = false;                               // last one doesn't have a next
  177.  
  178.           for (var x = newDirectories.length - 1; x >= 0; --x) {
  179.             this.data.splice(row + 1, 0, newDirectories[x]);
  180.           }
  181.  
  182.           this.updateParentIndices();
  183.           this.rowCount       = this.data.length;
  184.           this.treebox.rowCountChanged(row + 1, newDirectories.length);
  185.           this.data[row].open = true;
  186.         }
  187.  
  188.         this.treebox.invalidateRow(row);
  189.       }
  190.     }
  191.  
  192.     $('localdirname').removeAttribute('flex');                                                     // horizontal scrollbars, baby!
  193.  
  194.     var max = 125;
  195.     for (var z = 0; z < this.rowCount; ++z) {                                                     // this is what we CS folk like to call a TOTAL HACK
  196.       var x = { };    var y = { };    var width = { };    var height = { };                       // but, hey, it works so bite me
  197.       this.treebox.getCoordsForCellItem(z, this.treebox.columns["localdirname"], "text", x, y, width, height);
  198.  
  199.       if (x.value + width.value + 125 > max) {
  200.         max = x.value + width.value + 125;
  201.       }
  202.     }
  203.  
  204.     //if (doOpen) {
  205.       this.readjustHorizontalPosition(row);
  206.     //}
  207.  
  208.     $('localdirname').setAttribute('width', max);
  209.   },
  210.  
  211.   readjustHorizontalPosition : function(row) {
  212.     var x = { };    var y = { };    var width = { };    var height = { };
  213.     var first = this.treebox.getFirstVisibleRow()    >  0 ? this.treebox.getFirstVisibleRow()    : 0;
  214.     var last  = this.treebox.getLastVisibleRow() - 1 >= 0 ? this.treebox.getLastVisibleRow() - 1 : 0;
  215.  
  216.     this.treebox.getCoordsForCellItem(row != -1 ? row : 0, this.treebox.columns["localdirname"], "text", x, y, width, height);
  217.     this.treebox.scrollToHorizontalPosition(this.treebox.horizontalPosition + x.value - 60 >= 0 ? this.treebox.horizontalPosition + x.value - 60 : 0);
  218.  
  219.     var self = this;
  220.     var func = function() {
  221.       self.treebox.ensureRowIsVisible(last);
  222.       self.treebox.ensureRowIsVisible(first);
  223.     };
  224.     if (first < this.data.length) {
  225.       setTimeout(func, 0);
  226.     }
  227.   },
  228.  
  229.   addDirtyList : function(path) {
  230.     for (var x = 0; x < this.dirtyList.length; ++x) {
  231.       if (this.dirtyList[x] == path) {
  232.         return;
  233.       }
  234.     }
  235.  
  236.     this.dirtyList.push(path);
  237.   },
  238.  
  239.   updateParentIndices : function() {
  240.     for (var x = 0; x < this.data.length; ++x) {
  241.       this.data[x].parentIndex = this.indexOfPath(this.data[x].parent);                            // ah, beautiful
  242.     }
  243.   },
  244.  
  245.   indexOfPath : function(path) {                                                                   // binary search to find a path in the localDirTree
  246.     if (!path) {
  247.       return -1;
  248.     }
  249.  
  250.     var left      = 0;
  251.     var right     = this.data.length - 1;
  252.     var origPath  = path;
  253.     path          = path.replace(gSlash == "/" ? /\x2f/g : /\x5c/g, "\x01").toLowerCase();         // make '/' less than everything (except null really)
  254.  
  255.     while (left <= right) {
  256.       var mid      = Math.floor((left + right) / 2);
  257.       var dataPath = this.data[mid].sortPath;
  258.       if (gSlash == "/" && (this.data[mid].path == origPath || this.data[mid].path + "/" == origPath || this.data[mid].path == origPath + "/")) {
  259.         return mid;
  260.       } else if (dataPath == path || dataPath + "\x01" == path || dataPath == path + "\x01") {     // kind of complicated but what can you do
  261.         if (gSlash == "\\") {
  262.           return mid;
  263.         } else {
  264.           break;
  265.         }
  266.       } else if (path < dataPath) {
  267.         right = mid - 1;
  268.       } else if (path > dataPath) {
  269.         left  = mid + 1;
  270.       }
  271.     }
  272.  
  273.     if (gSlash == "/") {
  274.       for (var x = 0; x < this.data.length; ++x) {                                                 // last ditch effort b/c of we have to account for case
  275.         if (this.data[x].path == origPath || this.data[x].path + "/" == origPath || this.data[x].path == origPath + "/") {
  276.           return x;
  277.         }
  278.       }
  279.     }
  280.  
  281.     return -1;
  282.   },
  283.  
  284.   cdup : function() {
  285.     var parentIndex = this.getParentIndex(this.selection.currentIndex);
  286.  
  287.     if (parentIndex != -1) {
  288.       this.selection.select(parentIndex);
  289.     }
  290.   },
  291.  
  292.   findDirectory : null,
  293.  
  294.   changeDir : function(path, retry) {
  295.     if (path.indexOf("\\") == 0) {                                                                 // we can't handle network drives for now
  296.       error(gStrbundle.getString("noPermission"));
  297.       return;
  298.     }
  299.  
  300.     gLocalPath.value  = path;
  301.  
  302.     if (this.data.length == 0 || this.data[0].path.charAt(0) != gLocalPath.value.charAt(0)) {      // if dirTree is empty or we're switching to a new drive
  303.       var thePath;                                                                                 // we restart the tree
  304.  
  305.       if (gLocalPath.value.indexOf('/') == 0) {                                                    // linux
  306.         thePath = "/";
  307.         gSlash  = "/";
  308.       } else {                                                                                     // windows
  309.         if (gLocalPath.value.indexOf('\\') == -1) {
  310.           gLocalPath.value += "\\";
  311.         }
  312.  
  313.         thePath = gLocalPath.value.substring(0, gLocalPath.value.indexOf('\\') + 1);
  314.         gSlash  = "\\";
  315.       }
  316.  
  317.       try {                                                                                        // make sure we have a valid drive
  318.         var dir     = localFile.init(thePath);
  319.         var entries = dir.directoryEntries;
  320.       } catch (ex) {
  321.         error(gStrbundle.getString("noPermission"));
  322.         return;
  323.       }
  324.  
  325.       var oldRowCount = this.rowCount;
  326.       this.data       = new Array();
  327.       this.rowCount   = 0;
  328.       this.treebox.rowCountChanged(0, -oldRowCount);
  329.  
  330.       this.data.push({ open        : false,
  331.                        empty       : false,
  332.                        hasNext     : false,
  333.                        parentIndex : -1,
  334.                        children    : null,
  335.                        path        : thePath,
  336.                        leafName    : thePath,
  337.                        parent      : "",
  338.                        isHidden    : false,
  339.                        level       : 0,
  340.                        sortPath    : thePath.replace(gSlash == "/" ? /\x2f/g : /\x5c/g, "\x01").toLowerCase() });
  341.  
  342.       this.rowCount = 1;
  343.       this.treebox.rowCountChanged(0, 1);
  344.     }
  345.  
  346.     if (gSlash == "/") {                                                                           // error checking here for correct values in path
  347.       gLocalPath.value = gLocalPath.value.replace(/\x5c/g, "/");                                   // linux shouldn't have backslashes
  348.     } else {
  349.       gLocalPath.value = gLocalPath.value.replace(/\x2f/g, "\\");                                  // windows shouldn't have forward slashes
  350.     }
  351.  
  352.     gLocalPath.value   = gLocalPath.value.replace(/\\\.\.\\/g, "\\");                              // "\..\asdf"; doing relative paths not allowed
  353.     gLocalPath.value   = gLocalPath.value.replace(/\\\.\\/g,   "\\");                              // "\.\asdf"
  354.     gLocalPath.value   = gLocalPath.value.replace(/\\\.\.$/g,  "\\");                              // "\.."
  355.     gLocalPath.value   = gLocalPath.value.replace(/\\\.$/g,    "\\");                              // "\."
  356.     gLocalPath.value   = gLocalPath.value.replace(/\/\.\.\//g, "/");                               // "/../asdf"
  357.     gLocalPath.value   = gLocalPath.value.replace(/\/\.\//g,   "/");                               // "/./asdf"
  358.     gLocalPath.value   = gLocalPath.value.replace(/\/\.\.$/g,  "/");                               // "/.."
  359.     gLocalPath.value   = gLocalPath.value.replace(/\/\.$/g,    "/");                               // "/."
  360.  
  361.     if (gLocalPath.value != '/' && gLocalPath.value.charAt(gLocalPath.value.length - 1) == gSlash) {
  362.       gLocalPath.value = gLocalPath.value.substring(0, gLocalPath.value.length - 1);               // trim slashes at the end - ruins levels in dir
  363.     }
  364.  
  365.     if (gSlash == "\\" && gLocalPath.value.indexOf('\\') == -1) {                                  // if it's windows we add a slash to it: 'c:'->'c:\'
  366.       gLocalPath.value += "\\";
  367.     }
  368.  
  369.     if (gSlash == "/" && gLocalPath.value.charAt(0) != '/') {                                      // linux path has to start with '/'
  370.       gLocalPath.value = '/' + gLocalPath.value;
  371.     }
  372.  
  373.     var bestMatch;
  374.     var bestPath;
  375.     var localPathLevel = gLocalPath.value.match(gSlash == "/" ? /\x2f/g : /\x5c/g ).length;
  376.  
  377.     for (var x = 0; x < this.data.length; ++x) {                                                   // open parent directories til we find the directory
  378.       for (var y = this.data.length - 1; y >= x; --y) {
  379.         if ((gLocalPath.value.indexOf(this.data[y].path) == 0
  380.               || (gSlash == "\\" && gLocalPath.value.toLowerCase().indexOf(this.data[y].path.toLowerCase()) == 0))
  381.             && (this.getLevel(y) < localPathLevel || gLocalPath.value == this.data[y].path)) {
  382.           x         = y;
  383.           bestMatch = y;
  384.           bestPath  = this.data[y].path;
  385.           break;
  386.         }
  387.       }
  388.  
  389.       if (gLocalPath.value.indexOf(this.data[x].path) == 0
  390.           || (gSlash == "\\" && gLocalPath.value.toLowerCase().indexOf(this.data[x].path.toLowerCase()) == 0)) {
  391.         var dirty = false;
  392.  
  393.         for (var z = 0; z < this.dirtyList.length; ++z) {
  394.           if (this.dirtyList[z] == this.data[x].path) {
  395.             dirty = true;
  396.             break;
  397.           }
  398.         }
  399.  
  400.         this.ignoreSelect = true;
  401.         if (this.data[x].open && dirty) {
  402.           this.toggleOpenState(x);
  403.           this.toggleOpenState(x);
  404.         }
  405.  
  406.         if (this.data[x].empty && dirty) {
  407.           this.data[x].empty = false;
  408.           this.treebox.invalidateRow(x);
  409.         }
  410.  
  411.         if (!this.data[x].open && (gLocalPath.value != this.data[x].path || x == 0)) {
  412.           this.toggleOpenState(x);
  413.         }
  414.         this.ignoreSelect = false;
  415.  
  416.         if (gLocalPath.value == this.data[x].path
  417.             || (gSlash == "\\" && gLocalPath.value.toLowerCase() == this.data[x].path.toLowerCase())) {
  418.           gLocalPathFocus = gLocalPath.value;                                                      // directory approved
  419.           gFormHistory.addEntry(gLocalPath.getAttribute("autocompletesearchparam"), gLocalPath.value);
  420.           var sString  = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
  421.           sString.data = gLocalPath.value;
  422.           gPrefs.setComplexValue("folder", Components.interfaces.nsISupportsString, sString);      // remember last directory
  423.  
  424.           localTree.updateView();
  425.  
  426.           this.readjustHorizontalPosition(this.selection.currentIndex);
  427.  
  428.           if (gTreeSync && !gTreeSyncManager) {
  429.             treeSyncManager(true);
  430.           } else {
  431.             gTreeSyncManager = false;
  432.           }
  433.  
  434.           return;
  435.         }
  436.       }
  437.     }
  438.  
  439.     if (gTreeSyncManager) {
  440.       gTreeSyncManager = false;
  441.  
  442.       if (bestMatch) {
  443.         gLocalPath.value = bestPath;
  444.         gLocalPathFocus  = bestPath;
  445.         localTree.updateView();
  446.       }
  447.  
  448.       return;
  449.     }
  450.  
  451.     var findDirectory = localFile.init(gLocalPath.value);                                          // we didn't find the directory above
  452.  
  453.     if (localFile.verifyExists(findDirectory) && findDirectory.isDirectory() && (!retry || gLocalPath.value != path)) {
  454.       this.findDirectory = findDirectory;
  455.       var tempPath = gLocalPath.value;
  456.       this.selection.select(bestMatch);                                                            // it's possible the directory was added externally
  457.       localTree.refresh(true);                                                                     // and we don't have it on our dir list
  458.       this.findDirectory = null;
  459.       this.changeDir(tempPath, true);
  460.     }
  461.   },
  462.  
  463.   select : function(event) {
  464.     if (this.ignoreSelect) {
  465.       return;
  466.     }
  467.  
  468.     var index = this.selection.currentIndex;
  469.  
  470.     if (index >= 0 && index < this.data.length && this.data[index].path != gLocalPath.value) {
  471.       this.changeDir(this.data[index].path);
  472.     }
  473.   },
  474.  
  475.   click : function(event) {                                                                        // this is a special case: if we want the search to go away
  476.     var index = this.selection.currentIndex;
  477.  
  478.     if (index >= 0 && index < this.data.length && (this.data[index].path == gLocalPath.value && localTree.searchMode)) {
  479.       this.changeDir(this.data[index].path);
  480.     }
  481.   },
  482.  
  483.   keyPress : function(event) {
  484.     if (event.keyCode == 8) {                                                                      // backspace
  485.       this.cdup();
  486.     } else if (event.keyCode == 116) {                                                             // F5
  487.       event.preventDefault();
  488.       localTree.refresh(false, true);
  489.     }
  490.   },
  491.  
  492.   canDrop : function(index, orient) {
  493.     if (index == -1 || orient != 0 || !dragObserver.origin || dragObserver.origin == "external") {
  494.       return false;
  495.     }
  496.  
  497.     if (dragObserver.origin.indexOf('remote') != -1 && !gFtp.isConnected) {
  498.       return false;
  499.     }
  500.  
  501.     if (dragObserver.origin == 'localtreechildren') {                                              // can't move into a subdirectory of itself
  502.       for (var x = 0; x < localTree.rowCount; ++x) {
  503.         var dataPathSlash  = this.data[index].path  + (this.data[index].path.charAt(this.data[index].path.length - 1)   != gSlash ? gSlash : '');
  504.         var localTreeSlash = localTree.data[x].path + (localTree.data[x].path.charAt(localTree.data[x].path.length - 1) != gSlash ? gSlash : '');
  505.  
  506.         if (localTree.selection.isSelected(x) && ((dataPathSlash.indexOf(localTreeSlash) == 0 && localTree.data[x].isDirectory())
  507.                                                 || this.data[index].path == localTree.data[x].parent.path
  508.                                                 || this.data[index].path == localTree.data[x].parent.path + gSlash)) {
  509.           return false;
  510.         }
  511.       }
  512.     }
  513.  
  514.     return true;
  515.   },
  516.  
  517.   drop : function(index, orient) {
  518.     if (dragObserver.origin == 'localtreechildren') {
  519.       localTree.cut();
  520.       localTree.paste(this.data[index].path);
  521.     } else if (dragObserver.origin == 'remotetreechildren') {
  522.       var anyFolders = false;
  523.  
  524.       for (var x = 0; x < remoteTree.rowCount; ++x) {
  525.         if (remoteTree.selection.isSelected(x) && remoteTree.data[x].isDirectory()) {
  526.           anyFolders = true;
  527.           break;
  528.         }
  529.       }
  530.  
  531.       if (anyFolders && this.data[index].path != gLocalPath.value) {
  532.         var self      = this;
  533.         var path      = this.data[index].path;
  534.         var localPath = gLocalPath.value;
  535.         var func = function() { self.dropCallback(path, localPath); };
  536.         ftpObserver.extraCallback = func;
  537.       }
  538.  
  539.       var transferObj          = new transfer();
  540.       transferObj.localRefresh = gLocalPath.value;
  541.       transferObj.start(true,  '', this.data[index].path, '');
  542.     }
  543.   },
  544.  
  545.   dropCallback : function(newParent, localPath) {
  546.     var refreshIndex = this.indexOfPath(newParent);
  547.  
  548.     if (refreshIndex != -1) {
  549.       if (this.data[refreshIndex].open) {
  550.         this.toggleOpenState(refreshIndex, true);                                                  // close it up
  551.         this.data[refreshIndex].children = null;                                                   // reset its children
  552.         this.toggleOpenState(refreshIndex);                                                        // and open it up again
  553.       } else {
  554.         this.data[refreshIndex].children = null;                                                   // reset its children
  555.         this.data[refreshIndex].empty    = false;
  556.         this.treebox.invalidateRow(refreshIndex);
  557.       }
  558.  
  559.       var refreshIndex2 = this.indexOfPath(localPath);
  560.  
  561.       if (refreshIndex2 == -1) {
  562.         this.changeDir(localPath);
  563.       } else {
  564.         this.selection.select(refreshIndex2);
  565.       }
  566.     } else {
  567.       this.addDirtyList(newParent);
  568.     }
  569.   }
  570. };
  571.